package com.test.plugin;

import com.test.po.Page;
import com.test.util.PageUtil;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Connection;
import java.util.Properties;

/***
 * MyBatis 允许在已映射语句执行过程中的某一点进行拦截调用。默认情况下，MyBatis 允许使用插件来拦截的方法调用包括：
 *
 * Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
 * ParameterHandler (getParameterObject, setParameters)
 * ResultSetHandler (handleResultSets, handleOutputParameters)
 * StatementHandler (prepare, parameterize, batch, update, query)
 */
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})
})
public class MyPageHelper implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Page page = PageUtil.getLocalPage();
        if(page == null){
            return invocation.proceed();
        }
         System.out.println("ExamplePlugin...intercept:" + invocation.getMethod());

        // MetaObject 是 Mybatis 提供的一个用于访问对象属性的对象
        MetaObject metaObject = SystemMetaObject.forObject(invocation);

        System.out.println("当前拦截到的对象：" + metaObject.getValue("target"));
        System.out.println("SQL语句：" + metaObject.getValue("target.delegate.boundSql.sql"));
        System.out.println("SQL语句入参：" + metaObject.getValue("target.delegate.parameterHandler.parameterObject"));
        System.out.println("SQL语句类型：" + metaObject.getValue("target.delegate.parameterHandler.mappedStatement.sqlCommandType"));
        System.out.println("Mapper方法全路径名：" + metaObject.getValue("target.delegate.parameterHandler.mappedStatement.id"));

        // 修改 SQL 语句
        String newSQL = metaObject.getValue("target.delegate.boundSql.sql") + " limit 2";
        //metaObject.setValue("target.delegate.boundSql.sql", newSQL);
        System.out.println("修改后SQL语句：" + newSQL);
        return invocation.proceed();
    }

    /**
     * 为目标对象创建一个代理对象，使用 Plugin.wrap(target,this) 即可
     *
     * @param target 上次包装的代理对象
     * @return 本次包装过的代理对象
     */
    @Override
    public Object plugin(Object target) {//target是执行器对象
        return Plugin.wrap(target, this);//Mybatis提供的插件代理生成方法
    }

    /**
     * 获取自定义配置参数
     *
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {
        System.out.println(properties.toString());
    }
}
